package com.example.demo.service.impl;

import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.example.demo.dto.UserDto;
import com.example.demo.dto.UserQueryCriteria;
import com.example.demo.entity.User;
import com.example.demo.exception.EntityExistException;
import com.example.demo.exception.EntityNotFoundException;
import com.example.demo.mapper.UserMapper;
import com.example.demo.repository.UserRepository;
import com.example.demo.service.UserService;
import com.example.demo.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.List;
import java.util.Set;


/**
 * 用户信息操作实现类
 * @author zjj
 * @date 2021-04-20
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true,rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {
//    自动注入
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisUtils redisUtils;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDto create(User resource) {
        String uname = resource.getUserName();
        User users=userRepository.findByUserName(uname);
        if(users!=null){
            throw new EntityExistException(User.class,"userName",uname,"实体类中的","已经存在");
        }
//        获取当前系统的登录用户名
        String usname = SecurityUtils.getUsername();
        User userss=userRepository.findByUserName(usname);
        resource.setCreateId(userss.getId());
        resource.setCreateTime(new Timestamp(System.currentTimeMillis()));
        User user=userRepository.save(resource);
        return userMapper.toDto(user);
    }

    @Override
    public User checkUserInfo(String name, String pwd,String priKey) {
        User userInfo=userRepository.findByUserName(name);
        if(userInfo==null){
            throw new EntityExistException(User.class,"userName",name,"实体类中的","不存在");
        }
        RSA rsa = new RSA(priKey,null);
        String pwd_pri=new String(rsa.decrypt(userInfo.getPassword(), KeyType.PrivateKey));
        if(!pwd_pri.equals(pwd)){
            throw new EntityExistException(User.class,"password",pwd,"实体类中的","错误或者不存在");
        }
        return userInfo;
    }

    @Override
    public UserDto findByName(String userName) {
        User user;
        if(ValidationUtil.isEmail(userName)){
            user = userRepository.findByEmail(userName);
        } else {
            user = userRepository.findByUserName(userName);
        }
        if (user == null) {
            throw new EntityNotFoundException(User.class, "name", userName);
        } else {
            return userMapper.toDto(user);
        }
    }

    @Override
    public List<UserDto> findAll(UserQueryCriteria criteria) {
        Sort sort = criteria.getSort();
        List<User> users=userRepository.findAll(((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)),sort);
        return userMapper.toDto(users);
    }

    @Override
    public UserDto findById(Long id) {
        User user=userRepository.findById(id).orElseGet(User::new);
        ValidationUtil.isNull(user.getId(),"User","id",id);
        return userMapper.toDto(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(User user) {
        User us = userRepository.findById(user.getId()).orElseGet(User::new);
        ValidationUtil.isNull(us.getId(),"User","id",user.getId());

        User us1 = userRepository.findByUserName(us.getUserName());
        if(us1!=null&&!us.getId().equals(us1.getId())){
            throw new EntityExistException(User.class,"userName",user.getUserName());
        }
        //如果用户角色发生改变，需要手动清理redis缓存
        if(!user.getRoleId().equals(us.getRoleId())){
            String key = "role::loadPermissionByUser:"+us.getUserName();
            redisUtils.del(key);
            String key1 = "role::findByUsers_Id:"+us.getId();
            redisUtils.del(key1);
        }
        user = (User)BeanUtil.merge(user,us);
        User su_user = userRepository.findByUserName(SecurityUtils.getUsername());
        user.setUpdateId(su_user.getId());
        user.setUpdateTime(new Timestamp(System.currentTimeMillis()));

        userRepository.save(user);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Set<Long> ids) {
        User del_user=null;
        for(Long id : ids){
            del_user = userRepository.findById(id).orElseGet(User::new);
            del_user.setIsdel(false);
            userRepository.save(del_user);
        }
    }

}
